package org.platform.tool.util;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.SocketException;

/**
 * 这里成员变量不能用 static 修饰
 */

@Component
@Slf4j
public class FtpUtils {

    /**
     * Ftp服务器IP
     */
//    @Value("${ftp-ip}")
    private String ftpIP;

    /**
     * Ftp服务器端口与
     */
//    @Value("${ftp-port}")
    private Integer ftpPort;

    /**
     * Ftp服务器登录账号
     */
//    @Value("${ftp-username}")
    private String ftpUsername;

    /**
     * Ftp服务器登录密码
     */
//    @Value("${ftp-password}")
    private String ftpPassword;

    /**
     * 向Ftp服务器发送的文件路径
     */
//    @Value("${ftp-apply-path}")
    private String ftpApplyPath;

    /**
     * 本地Ftp服务器接收的文件路径
     */
//    @Value("${ftp-audit-path}")
    private String ftpAuditPath;

    Logger logger = Logger.getLogger(FtpUtils.class);

    /**
     * 获取FTPClient对象
     *
     * @return
     */
    public FTPClient getFTPClient() {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = new FTPClient();
            // 连接FTP服务器
            ftpClient.connect(ftpIP, ftpPort);
            // 登陆FTP服务器
            ftpClient.login(ftpUsername, ftpPassword);
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                logger.error("未连接到FTP，用户名或密码错误。");
                ftpClient.disconnect();
            } else {
                logger.info("FTP连接成功。");
            }
        } catch (SocketException e) {
            logger.error("FTP的IP地址可能错误，请正确配置。");
        } catch (IOException e) {
            logger.error("FTP的端口错误,请正确配置。");
        }
        return ftpClient;
    }

    /**
     * 从FTP服务器下载文件
     *
     * @param ftpPath   FTP服务器中文件所在路径 格式： ftptest/aa
     * @param localPath 下载到本地的位置 格式：H:/download
     * @param fileName  文件名称
     */
    public void downloadFtpFile(String ftpPath, String localPath, String fileName) {

        FTPClient ftpClient = null;

        try {
            ftpClient = getFTPClient();
            // 中文支持
            ftpClient.setControlEncoding("UTF-8");
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(ftpPath);

            File localFile = new File(localPath + File.separatorChar + fileName);
            OutputStream os = new FileOutputStream(localFile);
            ftpClient.retrieveFile(fileName, os);
            os.close();
            ftpClient.logout();

        } catch (FileNotFoundException e) {
            logger.error("没有找到" + ftpPath + "文件");
        } catch (SocketException e) {
            logger.error("连接FTP失败.");
        } catch (IOException e) {
            logger.error("文件读取错误。");
        } finally {
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                log.error("异常: ", e);
            }
        }
    }

    /**
     * 向FTP服务器上传文件
     *
     * @param station 站点 文件名格式  KnowApply_Station_1523501846356.txt
     * @param input   输入流(文件流,字节流...)
     * @return 成功返回true，否则返回false
     */
    public boolean uploadFile(String station, InputStream input) {
        boolean success = false;
        FTPClient ftpClient = null;
        try {
            int reply;
            ftpClient = getFTPClient();
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                return success;
            }
            // 中文支持
            ftpClient.setControlEncoding("UTF-8");
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();

            //创建目录
            if (createDir(ftpClient, ftpApplyPath)) {
                long l = System.currentTimeMillis();
                //缓冲的文件名
                String tempName = "KnowApply_" + station + "_" + l + ".temp";
                //真实的文件名
                String file = "KnowApply_" + station + "_" + l + ".txt";

                //创建文件
                if (ftpClient.storeFile(tempName, input)) {
                    logger.info(tempName + "文件创建【成功】");

                    //文件改名
                    if (ftpClient.rename(tempName, file)) {
                        logger.info(tempName + " 修改文件名【成功】,改为:" + file);
                        success = true;
                    } else {
                        logger.error(tempName + " 修改文件名【失败】");
                    }
                } else {
                    logger.info(tempName + "文件创建【失败】");
                }
            }
            input.close();
            ftpClient.logout();
        } catch (IOException e) {
            log.error("异常: ", e);
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }

    /**
     * 重命名远程FTP文件
     *
     * @return 是否成功
     * @throws IOException
     */
    public Boolean rename(String oldName, String newNName) {

        FTPClient ftpClient = null;
        Boolean result = false;
        try {
            ftpClient = getFTPClient();
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.changeWorkingDirectory(ftpApplyPath);
            result = ftpClient.rename(oldName, newNName);
        } catch (IOException e) {
            log.error("异常: ", e);
        } finally {
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                log.error("异常: ", e);
            }
        }

        logger.info("FTP服务器文件名更新标识：" + result);
        return result;
    }


    /**
     * 创建目录 如果存在,则切换到目录;如果不存在,则逐级创建,并且切换到目录
     *
     * @param ftp ftp
     * @param dir 文件目录 dir/dir1/dir2  (不能带盘符 如 D://dir)
     * @return
     */
    public boolean createDir(FTPClient ftp, String dir) {

        String d;
        try {
            //目录编码，解决中文路径问题
            d = new String(dir.getBytes("GBK"), "iso-8859-1");
            //尝试切入目录
            if (ftp.changeWorkingDirectory(d)) {
                return true;
            }
            String[] arr = dir.split("/");
            StringBuffer sbfDir = new StringBuffer();
            //循环生成子目录
            for (String s : arr) {
                sbfDir.append("/");
                sbfDir.append(s);
                //目录编码，解决中文路径问题
                d = new String(sbfDir.toString().getBytes("GBK"), "iso-8859-1");
                //尝试切入目录
                if (ftp.changeWorkingDirectory(d)) {
                    continue;
                }
                if (!ftp.makeDirectory(d)) {
                    logger.error("[失败] ftp创建目录{}：" + sbfDir.toString());
                    return false;
                }
                logger.info("创建ftp目录{}【成功】" + sbfDir.toString());
            }
            //将目录切换至指定路径
            return ftp.changeWorkingDirectory(d);
        } catch (Exception e) {
            logger.error("创建目录【失败】:", e);
            return false;
        }
    }


}